/*
XPTracker - Alternative Agile Tracking Tool
Copyright (C) 2006-2009  Stephen Starkey

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/
package org.xptracker.web;

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import fitnesse.wikitext.WidgetBuilder;
import net.sourceforge.stripes.security.controller.SecurityInterceptor;
import net.sourceforge.stripes.security.tag.SecureTag;
import org.apache.commons.logging.LogFactory;
import org.xptracker.domain.DomainUtil;
import org.xptracker.domain.WikiStyle;
import org.xptracker.inject.*;
import org.xptracker.services.reports.ReportFactory;
import static org.xptracker.util.UserConfigBase.*;
import org.xptracker.util.UserConfigString;
import org.xptracker.web.tags.InjectedLoopTag;
import org.xptracker.web.tags.WithStoryTotalsTag;
import org.xptracker.wiki.XpFitWidgetBuilder;
import org.xptracker.wiki.XpMarkdownWidgetBuilder;
import org.xptracker.wiki.render.MarkdownRenderer;
import org.xptracker.wiki.render.StandardWikiRenderer;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ContextSetupListener implements ServletContextListener {
  private Injector injector;

  public void contextInitialized(final ServletContextEvent servletContextEvent) {
    try {
      FileStructureBootstrapper bootstrapper = new FileStructureBootstrapper();
      Guice.createInjector(new SimpleSetupModule()).injectMembers(bootstrapper);
      bootstrapper.bootstrap();

      List<Module> modules = new ArrayList<Module>();
      modules.addAll(Arrays.asList(new SimpleSetupModule(), new AppModule(), new AuthModule(), new PortModule(),
          new ServletModule(), new AbstractModule() {
        protected void configure() {
          requestStaticInjection(SecureTag.class);
          requestStaticInjection(SecurityInterceptor.class);
          requestStaticInjection(WithStoryTotalsTag.class);
          requestStaticInjection(LoginFilter.class);
          requestStaticInjection(ReportFactory.class);
          requestStaticInjection(InjectedLoopTag.class);
          requestStaticInjection(GuiceInterceptor.class);
          requestStaticInjection(DomainUtil.class);
          requestStaticInjection(WebUtil.class);
        }
      }));
      UserConfigString config = new UserConfigString(PROPS_FILE, DB_TYPE, DEFAULT_DB_TYPE);
      modules.add(Modules.DB_MODULES.get(config.get()));
      injector = Guice.createInjector(modules);

      WikiStyle.fitnesse.setWikiRenderer(new StandardWikiRenderer(intercepted(new XpFitWidgetBuilder())));
      WikiStyle.markdown.setWikiRenderer(new MarkdownRenderer(intercepted(new XpMarkdownWidgetBuilder())));
      WikiStyle.bare.setWikiRenderer(new StandardWikiRenderer(intercepted(new BareWidgetBuilder())));

      injector.injectMembers(new DomainUtil());
      injector.injectMembers(new WebUtil());

      handleListeners(servletContextEvent, new ListenerHandler() {
        public void handleListener(ServletContextListener l) {
          l.contextInitialized(servletContextEvent);
        }
      });
    } catch (Exception e) {
      LogFactory.getLog(getClass()).error("Error initializing context", e);
    }
  }

  private WidgetBuilder intercepted(WidgetBuilder widgetBuilder) {
    widgetBuilder.addInterceptor(new GuiceInterceptor());
    return widgetBuilder;
  }

  public void contextDestroyed(final ServletContextEvent servletContextEvent) {
    handleListeners(servletContextEvent, new ListenerHandler() {
      public void handleListener(ServletContextListener l) {
        l.contextDestroyed(servletContextEvent);
      }
    });
  }

  private void handleListeners(ServletContextEvent servletContextEvent, ListenerHandler l) {
    String classStrings = servletContextEvent.getServletContext().getInitParameter("InjectedContextListeners");
    for (String className : classStrings.split(",")) {
      String trimmedName = className.trim();
      try {
        Class listenerClass = Class.forName(trimmedName);
        ServletContextListener listener = (ServletContextListener) listenerClass.newInstance();
        injector.injectMembers(listener);
        l.handleListener(listener);
      } catch (Exception e) {
        LogFactory.getLog(getClass()).error("Unable to handle class '" + trimmedName + "'", e);
      }
    }
  }

  private static interface ListenerHandler {
    void handleListener(ServletContextListener l);
  }

}
